using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Xml.Serialization;
using System.IO;

namespace SerialCommand {
    public class CommandCore {
        private SerialPort _port;
        private string _portName;
        private int _baudRate;
        private Parity _parity;
        private int _dataBits;
        private StopBits _stopBits;
        //private Stream _strm;
        private bool _readFullLine;
        //private Devices.Schema.Device _device;

        public delegate void DataRecvHandler(string data);
        public event DataRecvHandler DataRecvEvent;

        public delegate void ErrorHandler(string message);
        public event ErrorHandler ErrorEvent;

        //public Devices.Schema.Device Device {
        //    get { return _device; }
        //}

        //public string[,] ListCommands() {
        //    string[,] cmds;

        //    if (_device.Commands.Count > 0) {
        //        cmds = new string[_device.Commands.Count,2];


        //    }
        //}

        private void RaiseDataRecv(string data) {
            if (DataRecvEvent != null)
                DataRecvEvent(data);
        }

        private void RaiseErrorEvent(string message) {
            if (ErrorEvent != null)
                ErrorEvent(message);
        }

        public bool IsConnected() {
            if (_port == null)
                return false;
            if (_port.IsOpen)
                return true;
            return false;
        }

        public CommandCore( string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) {
            _portName = portName;
            _baudRate = baudRate;
            _parity = parity;
            _dataBits = dataBits;
            _stopBits = stopBits;
            //_device = device;
           
            _readFullLine = false;
          }

        public void Start() {
            // First make sure it's stoped
            Stop();

            _port = new SerialPort(_portName, _baudRate, _parity, _dataBits, _stopBits);
            _port.Handshake = Handshake.RequestToSend;
            _port.DataReceived += new SerialDataReceivedEventHandler(_port_DataReceived);
            _port.ErrorReceived += new SerialErrorReceivedEventHandler(_port_ErrorReceived);
            _port.Open();
        }

        public void Stop() {
            if (_port != null) {
                if (_port.IsOpen) {
                    _port.Close();
                }
                _port.Dispose();
                _port = null;
            }
        }

        public void Write(byte[] data, int offset, int count) {
            if (IsConnected()) {
                _port.Write(data, offset, count);
                //_port.Write(data, 0, data.Length);
            }
        }

        private void _port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) {
            //throw new Exception("The method or operation is not implemented.");
            RaiseErrorEvent(e.ToString());
        }

        private void _port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
            //throw new Exception("The method or operation is not implemented.");
            const int bufferSize = 1024;
            char[] data;
            
            if (_readFullLine) {
                RaiseDataRecv(_port.ReadLine());

            } else {
                data = new char[bufferSize];
                int iret = _port.Read(data, 0, bufferSize);
                RaiseDataRecv(new string(data, 0, iret));
            }
        }

        // C# to convert a string to a byte array.
        public static byte[] StrToByteArray(string str) {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            return encoding.GetBytes(str);
        }

        // C# to convert a byte array to string.
        public static string ByteArrayToStr(byte[] byteArr) {
            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            return enc.GetString(byteArr);
        }

        public static Devices.Schema.Device GetDeviceSettings(string sFile) {
            Devices.Schema.Device dev;
            XmlSerializer s = new XmlSerializer(typeof(Devices.Schema.Device));
            TextReader r = new StreamReader(sFile);
            dev = (Devices.Schema.Device)s.Deserialize(r);
            r.Close();

            return dev;
        }

        public static string[] GetComPortNames() {
            return SerialPort.GetPortNames();
        }
    }
}
